package com.spring.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.core.JdbcTemplate;

/*
java的配置类，代替xml配置文件
要完成三个功能
1、包扫描注解配置
2、引用外部的配置文件
3、声明第三方依赖的bean组件

 */


// 0、首先添加@Configuration，标识自己是配置类
@Configuration

// 1、包扫描注解配置，扫描多个包用{,}。@ComponentScan({"包1","包2",...})
@ComponentScan("com.spring.ioCStudy_01")

// 2、引用外部的配置文件
@PropertySource(value = "classpath:jdbc.properties")
public class JavaConfiguration {


    @Value("${ioCStudy.url}")
    private String url;
    @Value("${ioCStudy.driverClassName}")
    private String driverClassName;
    @Value("${ioCStudy.username}")
    private String userName;
    @Value("${ioCStudy.password}")
    private String password;

    // 3、声明第三方依赖的bean组件
    /*
    创建一个方法：
    返回值类型为你想要声明的第三方依赖bean组件的类型或其接口和父类
    方法的名字为默认beanId
    方法体自定义实现过程
    最后@Bean，会让配置类的方法创建的组件存储到ioC容器
     */
    /*
    @Bean的细节：
    1、注入组件Beanid：
    默认：方法名
    指定：name/value属性起名字，覆盖方法名
    2、第三方类的周期方法的指定：
    由于是第三方类，无法用@PostConstruct和@PreDestroy指定周期方法，
    只能通过@Bean的initMethod和destroyMethod属性来指定，指定的方法必须是在该第三方类中有的
    3、注入第三方组件如何引用其它的ioC组件
    (1)如果要引用的也是第三方类，调用其配置方法，如果不是，那么直接引用该类的变量名就行
    (2)让要引用的组件类对象作为形参声明，@Bean注解会自动寻找对应类型的组件对象为该形参声明赋值。
    必须爆炸ioC容器里有你要注入的这个组件，否则抛异常。
    如果有多个该类型的组件，需要使用形参声明的变量名指定，变量名要和其中一个组件的beanId一致




     */
    @Bean(name = "myDataSource", initMethod = "isKillWhenSocketReadTimeout", destroyMethod = "")
    @Scope(scopeName = ConfigurableBeanFactory.SCOPE_SINGLETON)
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUsername(userName);
        dataSource.setPassword(password);
        return dataSource;
    }


    // 3、(1)
    @Bean
    public JdbcTemplate jdbcTemplate() {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource());
        return jdbcTemplate;
    }

    // 3、(2)
    @Bean
    public JdbcTemplate jdbcTemplate(DruidDataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        return jdbcTemplate;
    }
}
